package JAVA300.第十一章多线程;

/**
 * 线程安全--利用synchronized
 */
public class thread_15_synchronized1_safe {
    public static void main(String[] args) {
        //一份资源
        Safe_web12306 tic = new Safe_web12306();
        new Thread(tic,"thread1").start();
        new Thread(tic,"thread2").start();
        new Thread(tic,"thread3").start();
    }
}

class Safe_web12306 implements Runnable {

    private int tickets = 10000;
    private boolean flag = true;

    @Override
    public void run() {

        try {

            Thread.sleep(200);

        } catch (InterruptedException e) {

            e.printStackTrace();
        }

       test();
       // test1();

    }

    //修改方法--线程安全 同步方法
    public synchronized void test(){
        if (tickets <=0){
            flag =false;
            return;
        }

            //模拟网络延迟--存在负数的情况
        try {

            Thread.sleep(200);

        } catch (InterruptedException e) {

                e.printStackTrace();
            }

            //如果有网络延迟等存在并发线程安全的情况

        System.out.println(Thread.currentThread().getName() + "--" + tickets--);//获取正在运行线程的名字



    }
    //同步块

    public void test1(){

        //存在两个变量修改 flag 和 tickets，将两个封装起来，this
        //单独锁tickets 用Integer强转一下 但是不安全 因为对象本身变化了 封装起来之后 仅仅是对象的属性变了
        synchronized (this){
            if (tickets <=0){
                flag =false;
                return;
            }

            //模拟网络延迟--存在负数的情况
            try {
                Thread.sleep(200);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }

            //如果有网络延迟等存在并发线程安全的情况


            System.out.println(Thread.currentThread().getName() + "--" + tickets--);//获取正在运行线程的名字


        }

    }

    public void test2(){

        //没有票的情况 这个不用锁 直接返回
        if (tickets <=0){
            flag =false;
            return;
        }

        //如果没有锁return的if段 多个人在面临最后一份资源时 还是会存在负数
        //最后一张票情况 进去之后还是需要判断的--double checking
        synchronized (this){
            if (tickets <=0){
                flag =false;
                return;
            }

            //模拟网络延迟--存在负数的情况
            try {
                Thread.sleep(200);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }

            //如果有网络延迟等存在并发线程安全的情况


            System.out.println(Thread.currentThread().getName() + "--" + tickets--);//获取正在运行线程的名字


        }

    }
}
